package com.lpf.MyGameSaveBackup.utils;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.log.StaticLog;
import com.alibaba.fastjson.JSONObject;
import com.lpf.MyGameSaveBackup.config.service.GlobalConfigService;
import org.apache.commons.lang3.StringUtils;

import java.io.InputStream;
import java.util.Map;
import java.util.UUID;

/**
 * @author: peifenglu@linkcm.com
 * @create: 2024-02-29
 * @Description:http/https请求工具类
 */
public class HttpCilentUtil {
    //设置连接超时时间，单位毫秒。
    private final static int TIMEOUT = 20000;
    //请求成功Http状态码
    public static final int HTTP_OK = 200;

    /**
     * 基于hutool.HttpRequest开发的通用发送http/https请求方法
     * @param url       请求地址
     * @param method    请求方式 支持GET,POST,PUT,DELETE
     * @param body      请求入参 以Map格式入参,GET请求会自动转换为url入参
     * @param headers   请求头
     * @param clazz     类名 将返回报文转换位该类
     * @return Object   请求返回报文 类型为clazz
     */
    public static <T> T sendRequest(String url, String method, Map<String,Object> body, Map<String, String> headers, Class<T> clazz){
        String result = sendRequest(url,method,body,headers);
        try {
            return JSONObject.parseObject(result,clazz);
        }
        catch (Exception e) {
            StaticLog.error("类型转换异常:",e);
            return null;
        }
    }

    /**
     * 基于hutool.HttpRequest开发的通用发送http/https请求方法
     * @param url       请求地址
     * @param method    请求方式 支持GET,POST,PUT,DELETE
     * @param body      请求入参 以Map格式入参,GET请求会自动转换为url入参
     * @param headers   请求头
     * @return String   请求返回报文
     *
     * 支持文件上传 body = {"file",new File()}
     */
    public static String sendRequest(String url, String method, Map<String,Object> body, Map<String, String> headers){
        //生成一个请求id,方便日志输出区分不同的请求
        String reqId = UUID.randomUUID().toString();

        //兼容https请求
        if (StringUtils.isEmpty(System.getProperties().getProperty("https.protocols")))
        {
            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        }

        HttpRequest req = null;
        //判断请求方式
        switch (method.toUpperCase()) {
            case "GET":
                req = HttpRequest.get(url);
                break;
            case "POST":
                req = HttpRequest.post(url);
                break;
            case "PUT":
                req = HttpRequest.put(url);
                break;
            case "DELETE":
                req = HttpRequest.delete(url);
                break;
            default:
                StaticLog.error("{}-请求方式method={}不存在",url,method);
                return null;
        }
        //请求头
        if (null != headers && !headers.isEmpty()) {
            for (String key : headers.keySet())
            {
                req.header(key,headers.get(key));
                if ("Content-Type".equals(key)) {
                    req.contentType(headers.get(key));
                }
            }
        }
        //入参
        if (null != body && body.size()>0){
            //GET请求需要把入参拼接到url中
            if ("GET".equalsIgnoreCase(method))
            {
                String paramStr = "";
                for (String key : body.keySet())
                {
                    if (StringUtils.isNotBlank(body.get(key)+""))
                    {
                        paramStr = paramStr + key + "=" +body.get(key)+"&";
                    }
                }
                if (paramStr.length()>0)
                {
                    //去掉结尾的&
                    paramStr = paramStr.substring(0,paramStr.length()-1);
                    //url中已有参数，用&连接
                    if (url.contains("?")) {
                        req.setUrl(url + "&" + paramStr);
                    }
                    //url没有入参，用?连接
                    else {
                        req.setUrl(url + "?" + paramStr);
                    }
                }
            }
            else
            {
                String contentType = req.header("Content-Type");
                if (StringUtils.isNotBlank(contentType) && contentType.toLowerCase().contains("json"))//json请求
                    req.body(JSONObject.toJSONString(body));
                else//form表单请求
                    req.form(body);
            }
        }

        showInfoLog("{}-请求地址:{}",reqId,req.getUrl());
        showInfoLog("{}-请求header:{}",reqId,JSONObject.toJSONString(req.headers()));
        showInfoLog("{}-请求入参:{}",reqId,JSONObject.toJSONString(body));
        HttpResponse res = req.timeout(TIMEOUT).execute();
        showInfoLog(reqId+"-返回状态:{},返回内容{}",res.getStatus(),res.body());
        if (HTTP_OK == res.getStatus())
        {
            return res.body();
        }
        else
        {
            StaticLog.error("{}-请求失败：status={},msg={}",reqId,res.getStatus(),res.body());
            return null;
        }
    }

    public static InputStream sendRequest_InputStream(String url, String method, Map<String,Object> body, Map<String, String> headers){
        //生成一个请求id,方便日志输出区分不同的请求
        String reqId = UUID.randomUUID().toString();

        //兼容https请求
        if (StringUtils.isEmpty(System.getProperties().getProperty("https.protocols")))
        {
            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        }

        HttpRequest req = null;
        //判断请求方式
        switch (method.toUpperCase()) {
            case "GET":
                req = HttpRequest.get(url);
                break;
            case "POST":
                req = HttpRequest.post(url);
                break;
            case "PUT":
                req = HttpRequest.put(url);
                break;
            case "DELETE":
                req = HttpRequest.delete(url);
                break;
            default:
                StaticLog.error("{}-请求方式method={}不存在",url,method);
                return null;
        }
        //请求头
        if (null != headers && !headers.isEmpty()) {
            for (String key : headers.keySet())
            {
                req.header(key,headers.get(key));
                if ("Content-Type".equals(key)) {
                    req.contentType(headers.get(key));
                }
            }
        }
        //入参
        if (null != body && body.size()>0){
            //GET请求需要把入参拼接到url中
            if ("GET".equalsIgnoreCase(method))
            {
                String paramStr = "";
                for (String key : body.keySet())
                {
                    if (StringUtils.isNotBlank(body.get(key)+""))
                    {
                        paramStr = paramStr + key + "=" +body.get(key)+"&";
                    }
                }
                if (paramStr.length()>0)
                {
                    //去掉结尾的&
                    paramStr = paramStr.substring(0,paramStr.length()-1);
                    //url中已有参数，用&连接
                    if (url.contains("?")) {
                        req.setUrl(url + "&" + paramStr);
                    }
                    //url没有入参，用?连接
                    else {
                        req.setUrl(url + "?" + paramStr);
                    }
                }
            }
            else
            {
                String contentType = req.header("Content-Type");
                if (StringUtils.isNotBlank(contentType) && contentType.toLowerCase().contains("json"))//json请求
                    req.body(JSONObject.toJSONString(body));
                else//form表单请求
                    req.form(body);
            }
        }

        showInfoLog("{}-请求地址:{}",reqId,req.getUrl());
        showInfoLog("{}-请求header:{}",reqId,JSONObject.toJSONString(req.headers()));
        showInfoLog("{}-请求入参:{}",reqId,JSONObject.toJSONString(body));
        HttpResponse res = req.timeout(TIMEOUT).execute();
        showInfoLog("{}-返回状态:{}",reqId,res.getStatus());
        if (HTTP_OK == res.getStatus())
        {
            return res.bodyStream();
        }
        else
        {
            StaticLog.error("{}-请求失败：status={},msg={}",reqId,res.getStatus(),res.body());
            return null;
        }
    }

    /**
     * 基于hutool.HttpRequest开发的通用发送http/https请求方法
     * @param url       请求地址
     * @param method    请求方式 支持GET,POST,PUT,DELETE
     * @param body      请求入参 以Map格式入参,GET请求会自动转换为url入参
     * @param headers   请求头
     * @return Map   调用信息
     *      req_url 请求地址 String
     *      req_header 请求头 Map<String, List<String>>
     *      req_body 请求入参 Map<String,Object>
     *      res_header 响应头 Map<String, List<String>>
     *      res_body 响应内容 String
     *      res_status 响应状态码 int
     *      res_obj 响应内容 根据clazz转换为对应实体，不传clazz 为空
     *
     * 支持文件上传 body = {"file",new File()}
     */
    public static ResponseVo sendRequestWithHeader(String url, String method, Map<String,Object> body, Map<String, String> headers, Class clazz){
        ResponseVo result = new ResponseVo();

        //生成一个请求id,方便日志输出区分不同的请求
        String reqId = UUID.randomUUID().toString();

        //兼容https请求
        if (StringUtils.isEmpty(System.getProperties().getProperty("https.protocols")))
        {
            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        }

        HttpRequest req = null;
        //判断请求方式
        switch (method.toUpperCase()) {
            case "GET":
                req = HttpRequest.get(url);
                break;
            case "POST":
                req = HttpRequest.post(url);
                break;
            case "PUT":
                req = HttpRequest.put(url);
                break;
            case "DELETE":
                req = HttpRequest.delete(url);
                break;
            default:
                StaticLog.error("{}-请求方式method={}不存在",url,method);
                return null;
        }
        //请求头
        if (null != headers && !headers.isEmpty()) {
            for (String key : headers.keySet())
            {
                req.header(key,headers.get(key));
                if ("Content-Type".equals(key)) {
                    req.contentType(headers.get(key));
                }
            }
        }
        //入参
        if (null != body && body.size()>0){
            //GET请求需要把入参拼接到url中
            if ("GET".equalsIgnoreCase(method))
            {
                String paramStr = "";
                for (String key : body.keySet())
                {
                    if (StringUtils.isNotBlank(body.get(key)+""))
                    {
                        paramStr = paramStr + key + "=" +body.get(key)+"&";
                    }
                }
                if (paramStr.length()>0)
                {
                    //去掉结尾的&
                    paramStr = paramStr.substring(0,paramStr.length()-1);
                    //url中已有参数，用&连接
                    if (url.contains("?")) {
                        req.setUrl(url + "&" + paramStr);
                    }
                    //url没有入参，用?连接
                    else {
                        req.setUrl(url + "?" + paramStr);
                    }
                }
            }
            else
            {
                String contentType = req.header("Content-Type");
                if (StringUtils.isNotBlank(contentType) && contentType.toLowerCase().contains("json"))//json请求
                    req.body(JSONObject.toJSONString(body));
                else//form表单请求
                    req.form(body);
            }
        }
        req.header("");
        HttpResponse res = req.timeout(TIMEOUT).execute();
        result.setReqUrl(url);
        result.setReqHeader(req.headers());
        result.setReqBody(body);
        result.setResHeader(res.headers());
        result.setResBody(res.body());
        result.setResStatus(res.getStatus());
        if (null != clazz)
            result.setResObj(JSONObject.parseObject(res.body(),clazz));
        showInfoLog("{}-接口信息:{}",reqId,JSONObject.toJSONString(result));
        return result;
    }


    private static void showInfoLog(String var1, Object var2, Object var3)
    {
        if ("info".equals(GlobalConfigService.GlobalConfig.getLogLevel()))
            StaticLog.info(var1,var2,var3);
    }
}
